package com.knowledge.plus.泛型.泛型方法;

/**
 * 示例：泛型方法中的类型推断
 * <p>
 * 当泛型方法的形参列表中有多个类型参数时，
 * 1. 在不指定类型参数的情况下，方法中声明的的类型参数为泛型方法中的几种类型参数的共同父类的最小级，直到 Object
 * 2. 在指定了类型参数的时候，传入泛型方法中的实参的数据类型必须为指定数据类型或者其子类
 *
 * @author aFei
 * @since 2023/10/30
 */
class Demo {

    // 这是一个简单的泛型方法  
    public static <T> T add(T x, T y) {
        return y;
    }

    public static void main(String[] args) {
        /**
         * 一、不显式地指定类型参数
         */
        // 传入的两个实参都是 Integer，所以泛型方法中的<T> == <Integer>
        int i = Demo.add(1, 2);

        // 传入的两个实参一个是 Integer，另一个是 Float，
        // 所以<T>取共同父类的最小级，<T> == <Number>
        Number number = Demo.add(1, 1.2);

        // 传入的两个实参一个是 Integer，另一个是 String，
        // 所以<T>取共同父类的最小级，<T> == <Object>
        Object obj = Demo.add(1, "asd");

        /**
         * 二、显式地指定类型参数
         */
        //（1）指定了<T> = <Integer>，所以传入的实参只能为 Integer 对象    
        int a = Demo.<Integer>add(1, 2);

        //（2）指定了<T> = <Integer>，所以不能传入 Float 对象
        // 编译错误
        // int b = GenericMethodDemo.<Integer>add(1, 2.2);

        //（3）指定<T> = <Number>，所以可以传入 Number 对象
        // Integer 和 Float 都是 Number 的子类，因此可以传入两者的对象
        Number c = Demo.<Number>add(1, 2.2);
    }
}
